﻿using System.IO;
using System.Text;

namespace LS.Screening.UI.Common
{
    public static class FileHelper
    {
        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileContent"></param>
        /// <param name="fileMode"></param>
        /// <param name="encoding"></param>
        public static void Write(string filePath, string fileContent, FileMode? fileMode = null, Encoding? encoding = null)
        {
            FileInfo fileWithDir = GetFileWithDir(filePath);
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            using (StreamWriter streamWriter = ((!fileWithDir.Exists) ? new StreamWriter(fileWithDir.Open(FileMode.Create, FileAccess.Write), encoding) : new StreamWriter(fileWithDir.Open(fileMode.GetValueOrDefault(FileMode.Truncate), FileAccess.Write), encoding)))
            {
                streamWriter.Write(fileContent);
                streamWriter.Flush();
                streamWriter.Close();
            }
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileData"></param>
        /// <param name="startPosition"></param>
        public static void Write(string filePath, byte[] fileData, int startPosition = -1)
        {
            FileInfo fileWithDir = GetFileWithDir(filePath);
            if (startPosition > 0 && !File.Exists(filePath))
            {
                return;
            }
            using (FileStream fileStream = ((!File.Exists(filePath)) ? fileWithDir.OpenWrite() : fileWithDir.Open(FileMode.OpenOrCreate)))
            {
                if (startPosition > 0)
                {
                    fileStream.Position = startPosition;
                }
                fileStream.Write(fileData, 0, fileData.Length);
                fileStream.Flush();
                fileStream.Close();
            }
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileContent"></param>
        /// <param name="fileMode"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static async Task WriteAsync(string filePath, string fileContent, FileMode? fileMode = null, Encoding? encoding = null)
        {
            FileInfo file = GetFileWithDir(filePath);
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            StreamWriter tw = ((!file.Exists) ? new StreamWriter(file.Open(FileMode.Create, FileAccess.Write), encoding) : new StreamWriter(file.Open(fileMode.GetValueOrDefault(FileMode.Truncate), FileAccess.Write), encoding));
            await tw.WriteAsync(fileContent);
            await tw.FlushAsync();
            tw.Close();
            tw.Dispose();
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileData"></param>
        /// <param name="startPosition"></param>
        /// <returns></returns>
        public static async Task WriteAsync(string filePath, byte[] fileData, int startPosition = -1)
        {
            FileInfo fileInfo = GetFileWithDir(filePath);
            if (startPosition > 0 && !File.Exists(filePath))
            {
                return;
            }
            using (FileStream fs = ((!File.Exists(filePath)) ? fileInfo.OpenWrite() : fileInfo.Open(FileMode.OpenOrCreate)))
            {
                if (startPosition > 0)
                {
                    fs.Position = startPosition;
                }
                await fs.WriteAsync(fileData, 0, fileData.Length);
                await fs.FlushAsync();
                fs.Close();
            }
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileData"></param>
        /// <param name="startPosition"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static async Task WriteAsync(string filePath, Stream fileData, int startPosition = -1)
        {
            FileInfo fileInfo = GetFileWithDir(filePath);
            if (startPosition > 0 && !File.Exists(filePath))
            {
                throw new Exception("要续传的文件不存在,请检查文件是否存在!");
            }

            using FileStream fs = ((!File.Exists(filePath)) ? fileInfo.OpenWrite() : fileInfo.Open(FileMode.OpenOrCreate));
            if (startPosition > 0)
            {
                fs.Position = startPosition;
            }

            byte[] buffer = new byte[1024];
            int offset = 0;
            for (int count = await fileData.ReadAsync(buffer, offset, 1024); count > 0; count = await fileData.ReadAsync(buffer, offset, 1024))
            {
                await fs.WriteAsync(buffer, offset, buffer.Length);
                offset += count;
            }

            await fs.FlushAsync();
            fs.Close();
        }

        /// <summary>
        /// 读取文件字节
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static byte[] ReadBytes(string filePath)
        {
            using FileStream fileStream = new FileStream(filePath, FileMode.Open);
            byte[] array = new byte[1024];
            List<byte> list = new List<byte>();
            int num = 0;
            int num2;
            do
            {
                fileStream.Seek(num, SeekOrigin.Begin);
                num2 = fileStream.Read(array, 0, array.Length);
                list.AddRange(array.Take(num2));
                num += num2;
            }
            while (num2 >= 1024);
            fileStream.Close();
            return list.ToArray();
        }

        /// <summary>
        /// 从指定的文件中读取文本
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string Read(string filePath, Encoding? encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            using StreamReader sr = new StreamReader(filePath, encoding);
            string content = sr.ReadToEnd();
            sr.Close();
            return content;
        }

        /// <summary>
        /// 从指定的文件中读取文本
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static async Task<string> ReadAsync(string filePath, Encoding? encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            using StreamReader sr = new StreamReader(filePath, encoding);
            string content = await sr.ReadToEndAsync();
            sr.Close();
            return content;
        }

        /// <summary>
        /// 读取文件字节
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="startPosition"></param>
        /// <param name="readLength"></param>
        /// <returns></returns>
        public static async Task<byte[]> ReadBytesAsync(string filePath, int startPosition = -1, int readLength = -1)
        {
            using FileStream fs = new FileStream(filePath, FileMode.Open);

            if (startPosition >= 0 && readLength > 0)
            {
                byte[] buf = new byte[readLength];
                fs.Seek(startPosition, SeekOrigin.Begin);
                int length = await fs.ReadAsync(buf, 0, buf.Length);
                if (length < buf.Length)
                {
                    return buf.Take(length).ToArray();
                }
                return buf;
            }
            return fs.ReadData();
        }

        /// <summary>
        /// 检查所给文件的目录是否存在，不存在则创建,并返回FileInfo对象
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static FileInfo GetFileWithDir(string filePath)
        {
            FileInfo fileInfo = new FileInfo(filePath);
            if (!Directory.Exists(fileInfo.DirectoryName))
            {
                Directory.CreateDirectory(fileInfo.DirectoryName);
            }
            return fileInfo;
        }

        /// <summary>
        /// 合并文件路径字符串，并创建中间的各级目录，合并后的路径必须是一个文件
        /// </summary>
        /// <param name="paths"></param>
        /// <returns></returns>
        public static string CombineWithDir(params string[] paths)
        {
            string text = Path.Combine(paths);
            string directoryName = Path.GetDirectoryName(text);
            if (!Directory.Exists(directoryName))
            {
                Directory.CreateDirectory(directoryName);
            }
            return text;
        }

        /// <summary>
        /// 根据通配符来查找文件
        /// </summary>
        /// <param name="searchPattern"></param>
        /// <param name="endWiths"></param>
        /// <returns></returns>
        public static List<string> GetPatternFiles(string searchPattern, params string[] endWiths)
        {
            List<string> list = new List<string>();
            string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
            string[] files = Directory.GetFiles(baseDirectory, searchPattern);
            string[] array = files;
            foreach (string path in array)
            {
                string s = Path.GetFileName(path);
                if (s.EndsWith(".pdb"))
                {
                    continue;
                }
                if (endWiths != null && endWiths.Count() > 0)
                {
                    if (endWiths.Any((string p) => s.EndsWith(p, StringComparison.OrdinalIgnoreCase)))
                    {
                        list.Add(s);
                    }
                }
                else
                {
                    list.Add(s);
                }
            }
            return list;
        }

        /// <summary>
        /// 指定分隔符，获取配置项对应的文件集合列表
        /// </summary>
        /// <param name="configString"></param>
        /// <param name="splite">分隔符,默认为：';', ','</param>
        /// <param name="endWiths">后缀(含通符时使用)，默认为：".dll", ".exe"</param>
        /// <returns></returns>
        public static List<string> GetFilesBySpliteConfigString(string configString, char[]? splite = null, params string[] endWiths)
        {
            if (string.IsNullOrEmpty(configString))
            {
                return new List<string>();
            }
            string[] configString2 = configString.Split((splite != null && splite.Length != 0) ? splite : new char[2] { ';', ',' }).Distinct().ToArray();
            return GetPatternFiles(configString2, endWiths);
        }

        /// <summary>
        /// 根据通配符来查找文件  后缀(含通符时使用)，默认为：".dll", ".exe"
        /// </summary>
        /// <param name="configString"></param>
        /// <param name="endWiths"></param>
        /// <returns></returns>
        public static List<string> GetPatternFiles(string[] configString, params string[] endWiths)
        {
            List<string> list = new List<string>();
            foreach (string text in configString)
            {
                if (text.Contains("*"))
                {
                    List<string> patternFiles = GetPatternFiles(text, (endWiths != null && endWiths.Length != 0) ? endWiths : new string[2] { ".dll", ".exe" });
                    list.AddRange(patternFiles);
                }
                else
                {
                    list.Add(text);
                }
            }
            return list.Distinct().ToList();
        }
    }
}
